﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using ProceduralGolf.geometry;

namespace ProceduralGolf.generation
{
    class Grass
    {

        Game game;

        Vector3[] positions;
        float[] angles;
        float[] scales;
        VertexBuffer[] vertices;
        IndexBuffer[] indices;
        Texture2D texture;

        Effect effect;

        VertexDeclaration vertexDeclaration;

        public static int NVERTICES = 4;
        public static int NINDICES = 12;

        public Grass(Game game, Vector3[] positions, VertexBuffer[] vertices, IndexBuffer[] indices, Texture2D texture)
        {
            this.game = game;
            effect = game.Content.Load<Effect>("textureshader");
            this.positions = positions;
            this.vertices = vertices;
            this.indices = indices;
            this.texture = texture;

            Random random = new Random();
            angles = new float[positions.Length];
            scales = new float[positions.Length];
            for (int i = 0; i < positions.Length; ++i)
            {
                angles[i] = (float)random.NextDouble() * MathHelper.TwoPi;
                scales[i] = MathHelper.Lerp(0.8f, 1.2f, (float)random.NextDouble());
            }

            vertexDeclaration = new VertexDeclaration(game.GraphicsDevice, VertexPositionTexture.VertexElements);
        }

        ~Grass()
        {
            foreach (VertexBuffer vertexBuffer in vertices)
                vertexBuffer.Dispose();

            foreach (IndexBuffer indexBuffer in indices)
                indexBuffer.Dispose();
        }

        //public void Draw(Matrix world, Matrix view, Matrix projection, Vector3 cameraPosition)
        //{
        //    game.GraphicsDevice.VertexDeclaration = vertexDeclaration;
        //    game.GraphicsDevice.Vertices[0].SetSource(vertices, 0, VertexPositionTexture.SizeInBytes);
        //    game.GraphicsDevice.Indices = indices;

        //    BoundingFrustum viewFrustum = new BoundingFrustum(view * projection);
        //    float maxDistance = 1000.0f;
            
        //    float currentAngle;
        //    Vector3 position;

        //    effect.Begin();

        //    effect.Parameters["View"].SetValue(view);
        //    effect.Parameters["Projection"].SetValue(projection);
        //    effect.Parameters["Texture"].SetValue(texture);
        //    for(int i = 0; i < positions.Length; ++i)
        //    {
        //        position = positions[i];
        //        currentAngle = angles[i];
        //        for(int j = 0; j < parts; ++j)
        //        {
        //            if (Vector3.Distance(cameraPosition, position) < maxDistance && viewFrustum.Contains(new BoundingSphere(position, GrassGenerator.WIDTH)) != ContainmentType.Disjoint)
        //            {
        //                effect.Parameters["World"].SetValue(world * Matrix.CreateScale(scales[i]) * Matrix.CreateRotationY(currentAngle) * Matrix.CreateTranslation(position));
        //                // draw
        //                foreach (EffectPass pass in effect.CurrentTechnique.Passes)
        //                {
        //                    pass.Begin();
        //                    game.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, NVERTICES, 0, NINDICES / 3);
        //                    pass.End();
        //                }
        //            }

        //            currentAngle += angle;
        //        }

        //    }
        //    effect.End();
        //}

        public void Draw(Matrix world, Matrix view, Matrix projection, Vector3 cameraPosition)
        {
            for (int i = 0; i < vertices.Length; ++i)
            {
                game.GraphicsDevice.VertexDeclaration = vertexDeclaration;
                game.GraphicsDevice.Vertices[0].SetSource(vertices[i], 0, VertexPositionTexture.SizeInBytes);
                game.GraphicsDevice.Indices = indices[i];

                effect.Begin();

                effect.Parameters["View"].SetValue(view);
                effect.Parameters["Projection"].SetValue(projection);
                effect.Parameters["Texture"].SetValue(texture);
                effect.Parameters["World"].SetValue(world);
                // draw
                foreach (EffectPass pass in effect.CurrentTechnique.Passes)
                {
                    pass.Begin();
                    game.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, NVERTICES * positions.Length, 0, NINDICES * positions.Length / 3);
                    pass.End();
                }
                effect.End();
            }
        }

    }
}
